package com.fw.service.auditlog.impl;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;

import com.fw.service.auditlog.AuditLogService;
import com.fw.service.auditlog.bean.AuditLogBean;
import com.fw.service.bean.SearchCriteriaBean;
import com.fw.service.bean.SearchResultBean;
import com.fw.service.persistence.dao.AuditLogDAO;
import com.fw.service.persistence.dto.AuditLog;
import com.fw.util.DateUtils;
import com.fw.util.PageRequestUtils;
import com.fw.util.StringUtils;

public class AuditLogServiceImpl implements AuditLogService {

    private static Logger log = Logger.getLogger(AuditLogServiceImpl.class.getName());

    @Autowired
    private AuditLogDAO auditLogDAO;

    @Override
    public AuditLogBean createAuditLog(AuditLogBean auditLogBean) {
	AuditLogBean resultBean = null;
	try {
	    if (auditLogBean != null) {
		AuditLog auditLog = new AuditLog();
		BeanUtils.copyProperties(auditLogBean, auditLog);
		auditLog.setServerIp(InetAddress.getLocalHost().getHostAddress());
		auditLog.setDateTime(StringUtils.formatDate(DateUtils.getCurrentDate(), StringUtils.PATTERN_DATETIME_PERSISTENCE));
		auditLog = auditLogDAO.save(auditLog);
		resultBean = new AuditLogBean();
		BeanUtils.copyProperties(auditLog, resultBean);
		resultBean.setId(auditLog.getId());
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return resultBean;
    }

    @Override
    public SearchResultBean<AuditLogBean> selectAuditLog(SearchCriteriaBean<AuditLogBean> searchCriteriaBean) {
	SearchResultBean<AuditLogBean> searchResultBean = null;
	try {
	    if (searchCriteriaBean != null) {
		AuditLogBean auditLogBean = searchCriteriaBean.getCriteriaBean();
		if (auditLogBean != null) {
		    final String logActionType = auditLogBean.getLogActionType();
		    final Long groupId = auditLogBean.getGroupId();
		    final Long userId = auditLogBean.getUserId();
		    final String fromDate = auditLogBean.getFromDate();
		    final String toDate = auditLogBean.getToDate();
		    Specification<AuditLog> specification = new Specification<AuditLog>() {
			@Override
			public Predicate toPredicate(Root<AuditLog> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
			    List<Predicate> predicates = new ArrayList<Predicate>();
			    if (logActionType != null) {
				predicates.add(cb.equal(root.<String> get("logActionType"), logActionType));
			    }
			    if (groupId != null) {
				predicates.add(cb.equal(root.<String> get("groupId"), groupId));
			    }
			    if (userId != null) {
				predicates.add(cb.equal(root.<String> get("userId"), userId));
			    }
			    if (fromDate != null) {
				predicates.add(cb.greaterThanOrEqualTo(root.<String> get("dateTime"), StringUtils.formatDate(
					DateUtils.getFromDate(StringUtils.parseDate(fromDate, StringUtils.PATTERN_DATE_UI)),
					StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }
			    if (toDate != null) {
				predicates.add(cb.lessThanOrEqualTo(root.<String> get("dateTime"), StringUtils.formatDate(
					DateUtils.getToDate(StringUtils.parseDate(toDate, StringUtils.PATTERN_DATE_UI)),
					StringUtils.PATTERN_DATETIME_PERSISTENCE)));
			    }

			    Predicate result = cb.conjunction();
			    for (Predicate predicate : predicates) {
				result.getExpressions().add(predicate);
			    }
			    return result;
			}
		    };
		    Page<AuditLog> page = auditLogDAO.findAll(specification, PageRequestUtils.getPageRequest(searchCriteriaBean));
		    if (page != null) {
			searchResultBean = new SearchResultBean<AuditLogBean>();
			searchResultBean.setTotalElements(page.getTotalElements());
			searchResultBean.setTotalPages(page.getTotalPages());
			List<AuditLogBean> content = new ArrayList<AuditLogBean>();
			List<AuditLog> auditLogs = page.getContent();
			if (auditLogs != null && !auditLogs.isEmpty()) {
			    for (AuditLog auditLog : auditLogs) {
				AuditLogBean bean = new AuditLogBean();
				BeanUtils.copyProperties(auditLog, bean);
				bean.setDateTime(StringUtils.formatDate(
					StringUtils.parseDate(auditLog.getDateTime(), StringUtils.PATTERN_DATETIME_PERSISTENCE),
					StringUtils.PATTERN_DATETIME_UI));
				bean.setId(auditLog.getId());
				content.add(bean);
			    }
			}
			searchResultBean.setContent(content);
		    }
		}
	    }
	} catch (Exception e) {
	    log.error(e.getMessage(), e);
	}
	return searchResultBean;
    }
}
